import base64
import socket
import threading
import datetime
import tarfile
import os
import struct
from OSS import OssClient
# Variables for holding information about connections
connections = []
total_connections = 0

IP = "192.168.34.58"
PORT = 3434
FORMAT = "utf-8"
SIZE = 1024
ADDR = (IP, PORT)
SERVER_DATA_PATH = "server_data"

pic_path = "img"

num = 0
# Client class, new instance created for each connected client
# Each instance has the socket and address that is associated with items
# Along with an assigned ID and a name chosen by the client
class Client(threading.Thread):

    def __init__(self, socket, address, id, name, signal):
        threading.Thread.__init__(self)
        self.socket = socket
        self.address = address
        self.id = id
        self.name = name
        self.signal = signal

    def __str__(self):
        return str(self.id) + " " + str(self.address) + " " + str(self.name)

    def merge(self):
        oss_client = OssClient('LTAI5tEwwSBita9Y9GLePsMa', 'hJvKLmKaae9urXl3pjjuGjnIbviW2d',
                               'oss-cn-chengdu.aliyuncs.com')
        oss_client.download(prefix="packet", download_path="new_download")
        oss_client.delete_buckets("packet")
    # Attempt to get data from client
    # If unable to, assume client has disconnected and remove him from server data
    # If able to and we get data back, print it in the server and send it back to every
    # client aside from the client that has sent it
    # .decode is used to convert the byte data into a printable string
    def run(self):
        while self.signal:
            try:
                data = self.socket.recv(SIZE)
                data = data.decode('utf-8')
                print(type(data))
                print(data)

                if data.startswith("ok") :
                    print(data[3:] + " success")
                    global num
                    num += 1
                    if num == 4:
                        self.merge()
                        num = 0

                # self.deal_data(data)
                # self.extent_tar()
            except Exception as e:
                print('错误类型是', e.__class__.__name__)
                print('错误明细是', e)

                print("Client " + str(self.address) + " has disconnected")
                self.signal = False
                connections.remove(self)
                break
            if data != "":
                pass
                # print("ID " + str(self.id) + ": " + str(data.decode(FORMAT)))
                # for client in connections:
                #     if client.id != self.id:
                #         client.socket.sendall(data)
            else:
                break

    def deal_data(self, buf):
        now_time = datetime.datetime.now().strftime('date%Y-%m-%d time%H_%M_%S')
        print("Accept from{0}".format(self.address))
        while True:
            struct.calcsize('128sq')

            if buf:
                if len(buf) == 136:

                    filename, filesize = struct.unpack('128sq', buf)
                    fn = str(now_time) + '_' + filename.decode().strip('\x00')

                    file_new_name = os.path.join(SERVER_DATA_PATH, fn)
                    print('newname is {0}, filesize {1}'.format(file_new_name, filesize))
                    received_size = 0
                    fp = open(file_new_name, 'wb')
                    print('start receiving')

                    while not received_size == filesize:
                        if filesize - received_size > 1024:
                            dat = self.socket.recv(1024)
                            received_size += len(dat)
                        else:
                            dat = self.socket.recv(1024)
                            received_size = filesize
                        fp.write(dat)
                    fp.close()
                else:
                    print("=====")
                    print('Files received')
                    break
            else:
                print("buf.length == 0!")
            print("=====")
            print('Files received')
            break

    def extent_tar(self):
        tar_path = os.walk(SERVER_DATA_PATH)
        for path, dir_list, file_list in tar_path:
            for dir_name in file_list:
                tarname = os.path.join(path, dir_name)
                if os.path.splitext(tarname)[-1] == '.tar':
                    print('TRUE')
                    tar = tarfile.open(tarname, 'r:')
                    file_names = tar.getnames()
                    for file_name in file_names:
                        tar.extract(file_name, SERVER_DATA_PATH)
                    tar.close()
                    print('tarfile extented')
                    os.remove(tarname)
                    print('tarfile deleted')


# Wait for new connections
def newConnections(socket):
    while True:
        sock, address = socket.accept()
        global total_connections
        print(sock)
        print(address)
        connections.append(Client(sock, address, total_connections + 1, "client-" + str(total_connections + 1), True))
        connections[len(connections) - 1].start()
        print("New connection at ID " + str(connections[len(connections) - 1]))
        total_connections += 1


def send(socket):
    while True:
        msg = input().strip()
        if len(msg) == 0:
            continue
        elif msg == "tar":
            for client in connections:
                client.socket.sendall(msg.encode(FORMAT))
                # receiveZip(client)  # 接收一次打包的文件
                while True:
                    data = client.socket.recv(SIZE)
                    client.deal_data(data)
                    # client.extent_tar()
                    break
                print("======================")
            continue
        print("---- msg: <" + msg + ">, send list ----")
        for client in connections:
            print(client)
            client.socket.sendall(msg.encode(FORMAT))


# def receiveZip(client):
#     print(f"start receiving from client {client.id}")
#     now_time = datetime.datetime.now().strftime('date%Y-%m-%d time%H_%M_%S')
#     flie_name = f"{now_time}_id{client.id}.zip"
#     # file = open(flie_name,"a",encoding=FORMAT) # w是只写模式，如果文件已存在则会先清空
#     file = open(flie_name, "wb")
#
#     while True:
#         try:
#             print("test point 1")
#             total_data = b''
#             data = client.socket.recv(SIZE)  # 执行这一句导致服务器异常关闭
#             # print(len(data))
#             total_data += data
#             file.write(total_data)
#             # if not data:
#             #     break
#             while len(data) > 0:
#                 # print(len(data))
#                 data = b''
#                 data += client.socket.recv(SIZE)
#                 total_data += data
#                 file.write(data)
#             # file.write(total_data.decode(FORMAT))
#             # file.write(total_data)
#             break
#         except Exception as e:
#             print(repr(e))
#
#     file.close()
#     print(f"接收完成，文件名为{flie_name}")

def main():
    # Create new server socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(ADDR)
    sock.listen(5)

    # Create new thread to wait for connections
    newConnectionsThread = threading.Thread(target=newConnections, args=(sock,))
    newConnectionsThread.start()

    sendThread = threading.Thread(target=send, args=(sock,))
    sendThread.start()


main()